package com.example.stringbufferlogger.Utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;

import com.example.stringbufferlogger.mapper.InterfaceMappingConfigMapper;
import com.example.stringbufferlogger.service.ReplayLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.List;

/**
 * OSS实现文件上传与下载工具类
 *
 * @author wyg
 * @date 2023/10/19
 */
@Component
public class OSSUtil {
    //日志
    private static final Logger logger = LoggerFactory.getLogger(OSSUtil.class);
    @Autowired
    private static ReplayLogService replayLogService;
    @Autowired
    private static InterfaceMappingConfigMapper interfaceMappingConfigMapper;
    /**
     * 将本地文件上传到OSS
     *
     * @param tempPath 本地文件路径
     * @param fileName 文件名
     * @param targPath OSS上文件路径，已添加日期（mmdd）作为区分
     * @throws FileNotFoundException
     */
    public static void uploadLocalFile(String tempPath, String fileName, String targPath) {

        OSS ossClient = null;
        InputStream inputStream = null;
        try {
            //查询数据库获取OSS连接参数，测试暂时写死
            String endpoint = "oss-cn-cd-tbcd-d01-a.ops.cloud-dev.group.cpic.com";
            String accessKeyId ="XlGWYSVWFvxTgVHq";
            String secretAccessKey = "mTTCPCuM7pFdlXAgcb8pyp2q2W3bMQ";
            //桶名称
            String bucketName = "endorse-parallel";

            // 创建OSSClient实例。
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
            // 简单上传--上传文件流。
            inputStream = new FileInputStream(tempPath + fileName);

            //上传到OSS的文件名
            String objectName = targPath + fileName;
            ossClient.putObject(bucketName, targPath + fileName, inputStream);
            ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withPrefix(objectName));
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            StringBuffer sb = new StringBuffer("文件上传到OSS成功，上传到OSS的对象名：");
            logger.info(objectName, sums, sb);
        } catch (OSSException e) {
            logger.info("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("Error Code: " + e.getErrorCode());
            logger.info("Request ID: " + e.getRequestId());
            logger.info("OSSException异常 ", e);
        } catch (ClientException e) {
            logger.info("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("ClientException异常", e);
        } catch (Exception e) {
            logger.info("oss upload file error. ", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                try {
                    ossClient.shutdown();
                }catch (Exception e){
                    logger.info("oss upload file error. ", e);
                }
            }
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.info("oss upload file error. ", e);
                }
            }
        }
    }


    /**
     * 将本地文件上传到OSS
     *
     * @param tempPath 本地文件路径
     * @param fileName 文件名
     * @throws FileNotFoundException
     */
    public static void uploadLocalFileTest(String tempPath, String fileName,String type) {

        OSS ossClient = null;
        InputStream inputStream = null;
        try {
            //查询数据库获取OSS连接参数，测试暂时写死
            String endpoint = "oss-cn-shanghai.aliyuncs.com";
            String accessKeyId ="LTAI5tBnH9UGmZ27kqc544WK";
            String secretAccessKey = "szdAe8QhU1bqKjov45ZNLdk3dGraOR";
            //桶名称
            String bucketName = "gpstest";

            // 创建OSSClient实例。
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
            // 简单上传--上传文件流。
            inputStream = new FileInputStream(tempPath + fileName);

            //上传到OSS的文件名
            String objectName = type+fileName;
            ossClient.putObject(bucketName, type + fileName, inputStream);
            ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withPrefix(objectName));
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            StringBuffer sb = new StringBuffer("文件上传到OSS成功，上传到OSS的对象名：");
            logger.info(objectName, sums, sb);
        } catch (OSSException e) {
            logger.info("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("Error Code: " + e.getErrorCode());
            logger.info("Request ID: " + e.getRequestId());
            logger.info("OSSException异常 ", e);
        } catch (ClientException e) {
            logger.info("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("ClientException异常", e);
        } catch (Exception e) {
            logger.info("oss upload file error. ", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                try {
                    ossClient.shutdown();
                }catch (Exception e){
                    logger.info("oss upload file error. ", e);
                }
            }
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.info("oss upload file error. ", e);
                }
            }
        }
    }

    /**
     * 从OSS下载文件到本地，并读取下载好的文件
     *
     * @param filename 文件名
     * @return
     */
    public static File getFileFromOSS(String localFilePath,String filename,String type) {
        OSS ossClient = null;
        File file = null;
        try {
            //查询数据库获取OSS连接参数，测试暂时写死
            String endpoint = "oss-cn-shanghai.aliyuncs.com";
            String accessKeyId ="LTAI5tBnH9UGmZ27kqc544WK";
            String secretAccessKey = "szdAe8QhU1bqKjov45ZNLdk3dGraOR";
            //桶名称
            String bucketName = "gpstest";

            //创建ossClient实例
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
            // p11目录读取有时间差，考虑到OSS也有
            String msg = "timeout";
            //下载的key
            String objectName =  type+"/"+filename;
            //判断文件是否在OSS中存在
            boolean flag = ossClient.doesObjectExist(bucketName, objectName);
            if (flag) {
                ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withPrefix(objectName));
                List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
                StringBuffer sb = new StringBuffer("将要下载的OSS的对象名：");
                logger.info(objectName, sums, sb);

                String targetDir = localFilePath + File.separator + type;
                File dir = new File(targetDir);
                // 检查目录是否存在，若不存在则创建
                if (!dir.exists()) {
                    if (dir.mkdirs()) {
                        logger.info("成功创建目录: {}", targetDir);
                    } else {
                        logger.error("无法创建目录: {}", targetDir);
                        return null;
                    }
                }
                // 拼接完整的文件路径
                String fullFilePath = targetDir +"\\"+ filename;
                // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
                ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(fullFilePath));
                file = new File(fullFilePath);

                logger.info("OSS下载的文件在本地存放的目录为:" + fullFilePath);

                int i;
                for (i = 0; i < 6; i++) {
                    if (file.exists()) {
                        logger.info(">>>>>>>OSS下载文件存放到本地成功>>>>>>");
                        msg = "success";
                        break;
                    } else {
                        Thread.sleep(20000);
                    }
                }
                logger.info("OSS接收文件等待秒数:" + i * 20);
                if ("timeout".equals(msg)) {
                    throw new Exception(objectName + "文件在本地未找到");
                }
            } else {
                logger.info(objectName + "文件在" + bucketName + "存储空间中不存在");
            }
        } catch (OSSException e) {
            logger.info("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("Error Code: " + e.getErrorCode());
            logger.info("Request ID: " + e.getRequestId());
            logger.info("OSSException异常", e);
        } catch (ClientException e) {
            logger.info("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("ClientException异常", e);
        } catch (Exception e) {
            logger.info("oss download file error.", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return file;
    }

    /**
     * 获取OSS文件信息
     *
     * @param filename 文件名称
     */
    public static void readFileFromOSS(String filename) {
        OSS ossClient = null;
        try {
            //查询数据库获取OSS连接参数，测试暂时写死
            String endpoint = "oss-cn-cd-tbcd-d01-a.ops.cloud-dev.group.cpic.com";
            String accessKeyId ="XlGWYSVWFvxTgVHq";
            String secretAccessKey = "mTTCPCuM7pFdlXAgcb8pyp2q2W3bMQ";
            //桶名称
            String bucketName = "endorse-parallel";
            //创建ossClient实例
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
            //下载的key
            String objectName = filename;
            //判断文件是否在OSS中存在
            boolean flag = ossClient.doesObjectExist(bucketName, objectName);
            if (flag) {
                //列举bucketName空间下，前缀是objectName的所有文件
                ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withPrefix(objectName));
                List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
                StringBuffer sb = new StringBuffer("readFileFromOSS下载的OSS对象名：");
                logger.info(objectName, sums, sb);
            } else {
                logger.info(objectName + "文件在" + bucketName + "存储空间中不存在");
            }

        } catch (OSSException e) {
            logger.info("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("Error Code: " + e.getErrorCode());
            logger.info("Request ID: " + e.getRequestId());
            logger.info("OSSException异常", e);
        } catch (ClientException e) {
            logger.info("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("ClientException异常", e);
        } catch (Exception e) {
            logger.info("oss download file error.", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    /**
     * 检查文件是否在 OSS 中存在
     * @param objectName 要检查的文件在 OSS 中的对象名
     * @return 如果文件存在返回 true，否则返回 false
     */
    public static boolean isFileExist(String objectName) {
        //查询数据库获取OSS连接参数，测试暂时写死
        String endpoint = "oss-cn-cd-tbcd-d01-a.ops.cloud-dev.group.cpic.com";
        String accessKeyId ="XlGWYSVWFvxTgVHq";
        String secretAccessKey = "mTTCPCuM7pFdlXAgcb8pyp2q2W3bMQ";
        //桶名称
        String bucketName = "endorse-parallel";

        OSS ossClient = null;
        try {
            // 创建 OSSClient 实例
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
            // 判断文件是否在 OSS 中存在
            return ossClient.doesObjectExist(bucketName, objectName);
        } catch (Exception e) {
            logger.error("检查 OSS 文件是否存在时出错", e);
            return false;
        } finally {
            // 关闭 OSSClient
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 从输入流上传文件到 OSS
     * @param inputStream 文件输入流
     * @param objectName 上传到 OSS 的对象名
     * @param type 新旧请求
     */
    public static void uploadFileFromStream(InputStream inputStream, String objectName, String type) {
        OSS ossClient = null;
        try {

            //查询数据库获取OSS连接参数，测试暂时写死
            String endpoint = "oss-cn-cd-tbcd-d01-a.ops.cloud-dev.group.cpic.com";
            String accessKeyId ="XlGWYSVWFvxTgVHq";
            String secretAccessKey = "mTTCPCuM7pFdlXAgcb8pyp2q2W3bMQ";
            //桶名称
            String bucketName = "endorse-parallel";
            // 创建 OSSClient 实例
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
            // 上传文件流到 OSS
            // 根据type值确定目标文件夹
            String targetFolder;
            if ("new".equalsIgnoreCase(type)) {
                targetFolder = "new/";
            } else if ("old".equalsIgnoreCase(type)) {
                targetFolder = "old/";
            } else {
                // 默认处理，可以根据需求调整
                targetFolder = "others/";
                logger.warn("未知的type类型: {}, 文件将被上传到others文件夹", type);
            }

            // 拼接完整的对象名（包含文件夹路径）
            String fullObjectName = targetFolder + objectName;
            ossClient.putObject(bucketName, fullObjectName, inputStream);
            // 列举 bucket 中前缀为 objectName 的所有文件
            ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withPrefix(objectName));
            for (OSSObjectSummary summary : objectListing.getObjectSummaries()) {
                if (summary.getKey().equals(objectName)) {
                    logger.info("文件上传到 OSS 成功，对象名: {}", objectName);
                    return;
                }
            }
            logger.error("文件上传到 OSS 后未找到对应对象，对象名: {}", objectName);
        } catch (Exception e) {
            logger.error("文件上传到 OSS 出错，对象名: {}", objectName, e);
        } finally {
            // 关闭 OSSClient
            if (ossClient != null) {
                ossClient.shutdown();
            }
            // 关闭输入流
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e) {
                    logger.error("关闭输入流出错", e);
                }
            }
        }
    }


    /**
     * 删除文件
     *
     * @param objectName
     */
    public static String ossDelFile(String objectName) {
        OSS ossClient = null;
        String str = null;
        try {
            //查询数据库获取OSS连接参数，测试暂时写死
            String endpoint = "oss-cn-cd-tbcd-d01-a.ops.cloud-dev.group.cpic.com";
            String accessKeyId ="XlGWYSVWFvxTgVHq";
            String secretAccessKey = "mTTCPCuM7pFdlXAgcb8pyp2q2W3bMQ";
            //桶名称
            String bucketName = "endorse-parallel";
            //创建ossClient实例
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);
            //判断文件是否在OSS中存在
            boolean flag = ossClient.doesObjectExist(bucketName, objectName);
            if (flag) {
                //列举bucketName空间下，前缀是objectName的所有文件
                ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withPrefix(objectName));
                List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
                // 删除文件。
                ossClient.deleteObject(bucketName, objectName);
                StringBuffer sb = new StringBuffer("OSS文件删除成功，删除的对象名：");
                logger.info(objectName, sums, sb);
                str = "";
            } else {
                str = objectName + "文件在OSS中不存在，删除失败！！！";
                logger.info(objectName + "文件在" + bucketName + "存储空间中不存在，删除失败！！！");
            }
        } catch (OSSException e) {
            logger.info("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("Error Code: " + e.getErrorCode());
            logger.info("Request ID: " + e.getRequestId());
            logger.info("OSSException异常", e);
        } catch (ClientException e) {
            logger.info("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network.");
            logger.info("Error Message: " + e.getErrorMessage());
            logger.info("ClientException异常", e);
        } catch (Exception e) {
            logger.info("oss download file error.", e);
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return str;
    }

}
